#include "../../sdk/dexsdk.h"
#include "../../sdk/time.h"

#define right 'd'
#define left 'a'
#define up 'w'
#define down 's'
#define quitgame 'q'
#define restart 'r'
#define startgame '1'
#define quit '3'
#define instruction '2'
#define x_start_area 60
#define y_start_area 0
#define x_end_area 260
#define y_end_area 200
#define block_size 20
#define xAdd 3
#define yAdd 0

#define WHITE 63
#define BLUE 9
#define GREEN 2
#define GRAY 56
#define BLACK 0


/*function prototypes*/
void erase(int x, int y, int w, int h);
void create_play_area();
void draw_box(int x, int y, int color);
void set_level();
void make_level();
void update(int mode,int x, int y,int mul);
void draw_menu_screen();
void draw_instruction();
void restart_level(int *x, int *y);
int can_move_right(int x, int y);
int can_move_left(int x, int y);
int can_move_up(int x, int y);
int can_move_down(int x, int y);


/*global variables*/
int play_area[block_size][block_size];
int level=0;
int xbound=0,ybound=0;
int xcursor=0,ycursor=0;
int xplayarea=0,yplayarea=0;

int main(){
    int x=x_start_area,y=y_start_area,i,j,a,b;
    char keypress=startgame;
    int l,k,c=0;;
    set_graphics(VGA_320X200X256);

    level=2;
    do{
        erase(1,1,400,220);
        draw_menu_screen();
        keypress=(char)getch();
       
       if(keypress==startgame){
         erase(120,40,100,100);
         erase(40,100,100,100);
         erase(40,140,100,100);
         erase(120,180,100,100);
         set_level();
         make_level();
         x=xcursor;y=ycursor;
       
           do{
             
               keypress=(char)getch();
               a=(x-x_start_area)/block_size;
               b=(y-y_start_area)/block_size;
               if(keypress == right){
                   if(can_move_right(a,b) == 1){
                       if(play_area[a+1][b] == 2){
                           play_area[a+1][b] = 0;
                           play_area[a+2][b] = 2;
                           draw_box(x+(block_size*2),y,GREEN); 
                       }
                       draw_box(x,y,BLACK);
                       x+=block_size;
                       draw_box(x,y, GRAY);
                   }
               }
               else if(keypress == left){
                   if(can_move_left(a,b) == 1){
                       if(play_area[a-1][b] == 2){
                           play_area[a-1][b] = 0;
                           play_area[a-2][b] = 2;
                           draw_box(x-(block_size*2),y,GREEN); 
                      } 
                       draw_box(x,y,BLACK);
                       x-=block_size;
                       draw_box(x,y,GRAY);
                   }
               }
               else if(keypress == down){
                   if(can_move_down(a,b) == 1){    
                       if(play_area[a][b+1] == 2){
                           play_area[a][b+1] = 0;
                           play_area[a][b+2] = 2;
                           draw_box(x,y+(block_size*2),GREEN); 
                      }
                       draw_box(x,y,BLACK);
                       y+=block_size;
                       draw_box(x,y,GRAY);
                   }
               }
               else if(keypress == up){
                   if(can_move_up(a,b) == 1){
                       if(play_area[a][b-1] == 2){
                           play_area[a][b-1] = 0;
                           play_area[a][b-2] = 2;
                           draw_box(x,y-(block_size*2),GREEN); 
                      }
                       draw_box(x,y,BLACK);
                       y-=block_size;
                       draw_box(x,y,GRAY);
                   }
               }
               else if(keypress == restart){
                  restart_level(&x, &y);
               }
               else if(keypress == quitgame){
                   break;
               }
           }while(1);
       }else if(keypress==instruction){
                erase(1,1,400,220);
                erase(120,40,100,100);
                erase(40,100,100,100);
                erase(40,140,100,100);
                erase(120,180,100,100);
               draw_instruction();
               keypress==(char)getch();
               if(keypress==startgame);
               else if(keypress==quit) break;
               
       }
    }while(keypress != quit);

    set_graphics(VGA_TEXT80X25X16);
    clrscr();
}

void draw_instruction(){
        write_text("INSTRUCTIONS",120,40,63); //title
        
        write_text("Your goal is to move the",400,70,63); //title
   write_text("blocks to the drop points",40,80,63);
        //menu options
        write_text("1 - Start",40,100,63); 
        write_text("2 - Instructions",40,140,63);
        write_text("3 - Quit",40,180,63);
}

void draw_menu_screen(){
        write_text("SOUKOBAN",120,40,63); //title

        //menu options
        write_text("1 - Start",40,100,63); 
        write_text("2 - Instructions",40,140,63);
        write_text("3 - Quit",40,180,63);
}
void update(int mode, int x,int y, int mul){

}

void create_play_area(){
    int i,j;
    for(i=x_start_area;i<x_end_area;i++){
        for(j=y_start_area;j<y_end_area;j++){
            write_pixel(i,j,62);
        }
    }
}

void draw_box(int x, int y, int color){
    int i,j;
    for(i=x;i<x+block_size;i++){
        for(j=y;j<y+block_size;j++){
            write_pixel(i,j,color);
        }
    }
}

void erase(int x, int y, int w, int h){ //basically covers an area with a black rectangle 
   int i,j;
   for (i=y;i<=(y+h);i++)
      for (j=x;j<=(x+w);j++)
         write_pixel(j,i,BLACK);
}

void restart_level(int *x, int *y){
   int i,j;
   erase(60,0,200,200);
   for(i=0;i<block_size;i++){
      for(j=0;j<block_size;j++){
         play_area[i][j] = 0;
      }
   }
   set_level();
   make_level();
   
   *x = xcursor; *y = ycursor;
}

int can_move_right(int x, int y){
   if(xcursor+block_size>=x_end_area ||
      play_area[x+1][y] == 1 ||
      (play_area[x+1][y] == 2 && xcursor+(block_size*2)>=x_end_area) ||
      (play_area[x+1][y] == 2 && play_area[x+2][y] == 2) ||
      (play_area[x+1][y] == 2 && play_area[x+2][y] == 1) 
      ) return 0; 
   else return 1;
}

int can_move_left(int x, int y){
   if(xcursor<=x_start_area ||
      play_area[x-1][y] == 1 ||
      (play_area[x-1][y] == 2 && xcursor-block_size<=x_start_area) ||
      (play_area[x-1][y] == 2 && play_area[x-2][y] == 2) ||
      (play_area[x-1][y] == 2 && play_area[x-2][y] == 1) 
      ) return 0; 
   else return 1;
}

int can_move_down(int x, int y){
   if(ycursor+block_size>=y_end_area ||
      play_area[x][y+1] == 1 ||
      (play_area[x][y+1] == 2 && ycursor+(block_size*2)>=y_end_area) ||
      (play_area[x][y+1] == 2 && play_area[x][y+2] == 1) || 
      (play_area[x][y+1] == 2 && play_area[x][y+2] == 2) 
      ) return 0; 
   else return 1;
}

int can_move_up(int x, int y){
   if(ycursor<=y_start_area ||
      play_area[x][y-1] == 1 ||
      (play_area[x][y-1] == 2 && ycursor-block_size<=y_start_area) ||
      (play_area[x][y-1] == 2 && play_area[x][y-2] == 1) ||
      (play_area[x][y-1] == 2 && play_area[x][y-2] == 2)
      ) return 0; 
   else return 1;
}

void set_level(){
   int x, y;
        switch(level){
                case 1:{
                   xbound=8,ybound=8;
                   for(x=0;x<xbound;x++) play_area[x][0]=1;
                   for(x=0;x<3;x++) for(y=1;y<4;y++) play_area[x][y]=1;
                   for(x=4;x<8;x++) for(y=1;y<3;y++) play_area[x][y]=1;
                   play_area[0][4]=1;play_area[7][3]=1;play_area[4][7]=1;
                   for(x=0;x<4;x++) for(y=5;y<8;y++) play_area[x][y]=1;
                   for(x=5;x<8;x++) for(y=4;y<8;y++) play_area[x][y]=1;
                   play_area[3][2]=0;play_area[2][4]=0;play_area[4][4]=0;
                   play_area[1][4]=3;play_area[3][1]=3;play_area[6][3]=3;play_area[4][6]=3;
                   play_area[3][3]=2;play_area[5][3]=2;play_area[4][5]=2;play_area[3][4]=2;
                   play_area[4][4]=8;
           break;
                }
                case 2:{
                xbound=8,ybound=8;
               for(x=0;x<8;x++) for(y=0;y<8;y++) if(y==0 || y==7 || x==0 || x==7) play_area[x][y] = 1;
               play_area[1][1] = 1; play_area[2][1] = 1;  
               play_area[6][1] = 1; play_area[1][2] = 1; 
               play_area[2][2] = 1; play_area[5][2] = 1; 
               play_area[6][2] = 1; play_area[1][3] = 1; 
               play_area[6][3] = 1; play_area[5][1] = 1;
               play_area[6][4] = 1; play_area[3][5] = 1; 
               play_area[5][5] = 2; play_area[3][4] = 2;
               play_area[4][3] = 2; play_area[4][5] = 2;
               play_area[3][1] = 3; play_area[4][1] = 3;
               play_area[4][2] = 3; play_area[5][3] = 3;
               play_area[3][6] = 8;
                        
         break;
                }
                case 3:{
         break;
                }
                case 4:{
         break;
                }
        }

}

void make_level(){
    int i,j;
    int x=xAdd,y=yAdd;
    for(i=0;i<xbound;i++){
        for(j=0;j<ybound;j++){
            if(play_area[i][j]==1)draw_box((i+x)*block_size,(j+y)*block_size,WHITE); //wall
            else if(play_area[i][j]==3) draw_box((i+x)*block_size,(j+y)*block_size,BLUE); //target
            else if(play_area[i][j]==2) draw_box((i+x)*block_size,(j+y)*block_size,GREEN); //box
            else if(play_area[i][j]==8) {draw_box((i+x)*block_size,(j+y)*block_size,GRAY);xcursor=block_size*(i+x);ycursor=block_size*(j+y); } //man
        }
    }
    xplayarea=(x+xbound)*block_size;
    yplayarea=(y+ybound)*block_size;
}

